﻿using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AgentSystem.AgentCreator.Sbpel.Activities
{
    /// <summary>
    /// Activity class for representing a sequence
    /// </summary>
    public class SequenceActivity : AbstractActivity
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="SequenceActivity"/> class.
        /// </summary>
        /// <param name="Name">The name.</param>
        public SequenceActivity(AbstractActivity parent, string name) : base(parent)
        {
            Name = name;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="SequenceActivity"/> class.
        /// </summary>
        public SequenceActivity(AbstractActivity parent) : this(parent, string.Empty) { }

        /// <returns>
        /// String representing C# code.
        /// The first sequence child is the direct descendent.
        /// The following children are lower in the tree.
        /// </returns>
        public override CodeObject[] GetCodeDom()
        {
            IList<CodeObject> returnedCodeObjects = new List<CodeObject>();

            CodeMemberMethod sequenceMethod = new CodeMemberMethod();
            sequenceMethod.Attributes = MemberAttributes.Private;
            sequenceMethod.Name = string.Format("Sequence{0}", Name);

            returnedCodeObjects.Add(sequenceMethod);

            //All the child elements are converted into statements
            foreach (var activity in ChildActivities)
            {
                bool invokedDirectChild = false;
                foreach (var codeDome in activity.GetCodeDom())
                {
                    if (codeDome is CodeStatement)
                    {
                        sequenceMethod.Statements.Add(codeDome as CodeStatement);
                    }
                    else if (codeDome is CodeMemberMethod && !invokedDirectChild)
                    {
                        //The first child method is invoked, being a direct descendent
                        invokedDirectChild = true;
                        var invokeMethod = new CodeMethodInvokeExpression( 
                            null, 
                            (codeDome as CodeMemberMethod).Name, // mehtod name
                            new CodeExpression[]{ }); // no parameters
                        sequenceMethod.Statements.Add(invokeMethod);

                        returnedCodeObjects.Add(codeDome);
                    }
                    else
                    {
                        returnedCodeObjects.Add(codeDome);
                    }
                }
            }

            return returnedCodeObjects.ToArray();
        }
    }
}
